package org.zoomdev.zoom.server;

import jakarta.servlet.DispatcherType;
import jakarta.servlet.Filter;
import org.eclipse.jetty.ee10.servlet.FilterHolder;
import org.eclipse.jetty.ee10.webapp.WebAppContext;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.util.thread.VirtualThreadPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zoomdev.zoom.common.exceptions.ZoomException;
import org.zoomdev.zoom.common.utils.PathUtils;
import org.zoomdev.zoom.web.WebService;

import java.util.EnumSet;
import java.util.Map;

public class WebAppServer {

    public static final int DEFAULT_PORT = 8090;

    public static final String DEFAULT_CONTEXT_PATH = "/";


    private static final Logger log = LoggerFactory.getLogger(WebAppServer.class);
    private final int port;
    private final String contextPath;
    private final Filter filter;
    private WebAppContext webAppContext;
    private Server server;
    private Map<String, String> params;

    public WebAppServer() {
        this(DEFAULT_PORT);
    }

    public WebAppServer(int port) {
        this(port, DEFAULT_CONTEXT_PATH);
    }


    public WebAppServer(int port, String contextPath) {
        this(port, contextPath, null);
    }

    public WebAppServer(int port, String contextPath, Filter filter) {
        this.port = port;
        this.contextPath = contextPath;
        this.filter = filter;

    }


    public void startup() throws Exception {
        if (server != null) return;

        VirtualThreadPool threadPool = new VirtualThreadPool();
        server = new Server(threadPool);

        // 创建连接器
        ServerConnector connector = new ServerConnector(server);
        connector.setPort(port);
        connector.setAcceptQueueSize(1024);     // 连接等待队列
        connector.setIdleTimeout(30000);        // 空闲超时

        connector.setReuseAddress(true);        // 启用端口复用

        server.addConnector(connector);

        server.setHandler(createHandler());
        server.start();
        System.out.println("Server start on port: " + port);

    }

    protected WebAppContext createHandler() {
        webAppContext = new WebAppContext();
        webAppContext.setBaseResourceAsString(PathUtils.getRootPath());
        webAppContext.setContextPath(contextPath);
        FilterHolder holder;
        if (filter != null) {
            holder = new FilterHolder(filter);
        } else {
            holder = new FilterHolder(WebService.class);
            if (params != null) {
                holder.setInitParameters(params);
            }
        }
        webAppContext.addFilter(holder, "/*", EnumSet.of(DispatcherType.REQUEST));
        webAppContext.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");
        webAppContext.setInitParameter("org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false");
        return webAppContext;
    }

    public void join() {
        if (server == null) {
            return;
        }
        try {
            server.join();
        } catch (InterruptedException e) {

        }
    }

    public void restart() {


        try {
            webAppContext.stop();
        } catch (Exception e) {
            throw new ZoomException(e);
        }

        try {
            server.stop();
        } catch (Exception e) {
            throw new ZoomException("停止服务失败", e);
        }

        try {
            webAppContext.start();
        } catch (Exception e) {
            throw new ZoomException(e);
        }


        try {
            server.start();
        } catch (Exception e) {
            throw new ZoomException("启动服务失败", e);
        }
    }

    public void setInitParameters(Map<String, String> data) {
        this.params = data;
    }

//    private String getStoreDir() {
//        log.info("Server root path:" + PathUtils.getRootPath());
//        String storeDir = PathUtils.getRootPath() + "session" + contextPath;
//        log.info("Store session to :" + storeDir);
//        if ("\\".equals(File.separator))
//            storeDir = storeDir.replaceAll("/", "\\\\");
//        File file = new File(storeDir);
//        if (!file.exists()) {
//            file.mkdirs();
//        }
//        return storeDir;
//    }
//
//    private void persistSession(WebAppContext webApp) throws IOException {
//        String storeDir = getStoreDir();
//
//        SessionManager sm = webApp.getSessionHandler().getSessionManager();
//        if (sm instanceof HashSessionManager) {
//            ((HashSessionManager) sm).setIdleSavePeriod(1);
//            ((HashSessionManager) sm).setStoreDirectory(new File(storeDir));
//            return;
//        }
//
//        HashSessionManager hsm = new HashSessionManager();
//        hsm.setStoreDirectory(new File(storeDir));
//        hsm.setIdleSavePeriod(1);
//        SessionHandler sh = new SessionHandler();
//        sh.setSessionManager(hsm);
//        webApp.setSessionHandler(sh);
//    }

    public void shutdown() {
        if (server != null) {
            try {
                server.stop();
            } catch (Exception e) {

            }
            server.destroy();
            server = null;
        }


        if (webAppContext != null) {
            try {
                webAppContext.stop();
            } catch (Exception e) {
                throw new ZoomException(e);
            } finally {
                webAppContext.destroy();
                webAppContext = null;
            }

        }
    }

    public boolean isAlive() {

        return webAppContext.isAvailable();
    }


}
